<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body style="background-color: #1e293b;color: #c9d1d9;">
    <h1 id="app">{{name}}</h1>
    <script>
        //副作用函数栈，存放所有副作用函数
        const e_stack = new Set();
        //正在执行的副作用函数
        let activeEffect = null;
        
        //判断是否是对象
         function isObject(value){
            return typeof value === 'object' && value !== null
         }
        /**
         * 创建响应式数据
         * @param [object]: 普通对象
         * @return [Proxy]: 代理对象
         */
        function reactive(obj){
          if(!isObject(obj)) return;
          
          return new Proxy(obj,{
            get(target,key){
              if(activeEffect) e_stack.add(activeEffect)
              return target[key]
            },
            set(target,key,value){
              target[key] = value;
              e_stack.forEach( (fn) => fn() )
              return true;
            }
          })
        }
       
       /**
        * 注册副作用函数
        * @param [function]: 需要注册的副作用函数
        */
       function registEffect(fn){
         if(typeof fn !== 'function') return
         activeEffect = fn    //记录正在执行的副作用函数
         fn()                 //调用副作用函数         
         activeEffect = null  //重置全局变量
       }
       
        //将对象设置为响应式数据
        const data = reactive( { name : 'xiaohong', age: 3} )

        //副作用函数
        function effectName(){
          console.log('effectName...',data.name);  //压入stack
        }
        registEffect(effectName)
        registEffect(function effectAge(){
          console.log('effectAge...',data.age);    //压入stack
        })
        
        setTimeout(()=>{
           data.name = 'newking'
        },1000)
     
    </script> 
  </body>
</html>